package cike.com.media_picker

import android.app.Activity
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.util.Log
import android.widget.ImageView
import androidx.annotation.NonNull
import androidx.annotation.Nullable
import androidx.fragment.app.Fragment
import cike.com.media_picker.ImageLoaderUtils.assertValidRequest
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.engine.CompressFileEngine
import com.luck.picture.lib.engine.UriToFileTransformEngine
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnKeyValueResultCallbackListener
import com.luck.picture.lib.interfaces.OnRecordAudioInterceptListener
import com.luck.picture.lib.interfaces.OnResultCallbackListener
import com.luck.picture.lib.utils.SandboxTransformUtils
import com.luck.pictureselector.GlideEngine

import com.yalantis.ucrop.UCrop
import com.yalantis.ucrop.UCropImageEngine
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import top.zibin.luban.Luban
import top.zibin.luban.OnNewCompressListener
import java.io.File


class MediaPickerPlugin : FlutterPlugin, ActivityAware, MethodCallHandler {
    /// The MethodChannel that will the communication between Flutter and native Android
    ///
    /// This local reference serves to register the plugin with the Flutter Engine and unregister it
    /// when the Flutter Engine is detached from the Activity
    private lateinit var channel: MethodChannel
    private lateinit var activity: Activity

    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "media_picker")
        channel.setMethodCallHandler(this)
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        activity = binding.getActivity()
    }


    override fun onMethodCall(@NonNull call: MethodCall, @NonNull  result:Result) {
        Log.i("media_picker", call.method);
        if (call.method == "chooseImg") {
            pickerImage(call.arguments, result)
        } else if (call.method == "chooseVideo") {
            pickerVideo(call.arguments, result)
        } else if (call.method == "chooseAudio") {
            pickerAudio(call.arguments, result)
        } else {
            result.notImplemented()
        }
    }


    private fun pickerImage(argument: Any?, result: Result) {
        if (argument == null || argument !is Map<*, *>) return;
        val isEnableCrop = argument["isCrop"]?.let { it as Boolean } ?: false
        val isCompress = argument["isCompress"]?.let { it as Boolean } ?: true
        val isGif = argument["isGif"]?.let { it as Boolean } ?: true
        val compressQuality = argument["quality"]?.let { it as Int } ?: 80
        val isCamera = argument["isCamera"]?.let { it as Boolean } ?: true
        val maxNumber = argument["max"]?.let { it as Int } ?: 1

        PictureSelector.create(activity)
            .openGallery(SelectMimeType.ofImage())
            .setImageEngine(GlideEngine.createGlideEngine())
            .setMaxSelectNum(maxNumber)
            .isDisplayCamera(isCamera)
            .isGif(isGif)
            .isWebp(false)
            .isBmp(false)
            .setSandboxFileEngine { context, srcPath, mineType, call ->
                if (call != null) {
                    val sandboxPath =
                        SandboxTransformUtils.copyPathToSandbox(context, srcPath, mineType)
                    call.onCallback(srcPath, sandboxPath);
                }
            }
            .apply {
                if (isCompress) {
                    setCompressEngine(CompressFileEngine { context, source, call ->
                        Luban.with(context).load(source).ignoreBy(100)
                            .setCompressListener(object : OnNewCompressListener {
                                override fun onStart() {}
                                override fun onSuccess(source: String, compressFile: File) {
                                    call?.onCallback(source, compressFile.absolutePath)
                                }

                                override fun onError(source: String, e: Throwable) {
                                    call?.onCallback(source, null)
                                }
                            }).launch()
                    })
                }
            }
            .apply {
                if (isEnableCrop) {
                    setCropEngine { fragment, srcUri, destinationUri, dataSource, requestCode ->
                        val uCrop = UCrop.of(srcUri, destinationUri, dataSource)
                        uCrop.setImageEngine(object : UCropImageEngine {
                            override fun loadImage(
                                context: Context,
                                url: String,
                                imageView: ImageView
                            ) {
                                Glide.with(context).load(url).into(imageView)
                            }

                            override fun loadImage(
                                context: Context?,
                                url: Uri?,
                                maxWidth: Int,
                                maxHeight: Int,
                                call: UCropImageEngine.OnCallbackListener<Bitmap?>?
                            ) {
                                if (!assertValidRequest(context)) {
                                    return
                                }
                                Glide.with(context!!).asBitmap().override(maxWidth, maxHeight)
                                    .load(url).into(object : CustomTarget<Bitmap?>() {
                                        override fun onResourceReady(
                                            resource: Bitmap,
                                            @Nullable transition: Transition<in Bitmap?>?
                                        ) {
                                            if (call != null) {
                                                call.onCall(resource)
                                            }
                                        }

                                        override fun onLoadFailed(@Nullable errorDrawable: Drawable?) {
                                            if (call != null) {
                                                call.onCall(null)
                                            }
                                        }

                                        override fun onLoadCleared(@Nullable placeholder: Drawable?) {}
                                    })
                            }
                        })
                        uCrop.withOptions(UCrop.Options().apply {
                            isForbidSkipMultipleCrop(true); //多图裁剪时是否支持跳过
                            isCropDragSmoothToCenter(true); //图片是否跟随裁剪框居中
                            isForbidCropGifWebp(true); //是否禁止裁剪gif和webp
                            isDarkStatusBarBlack(true); //状态栏字体颜色是否黑色模式

                        })
                        fragment.activity?.let { uCrop.start(it, fragment, requestCode) }
                    }
                }
            }
            .forResult(object : OnResultCallbackListener<LocalMedia?> {
                override fun onCancel() {
                    Log.i("pickerImage", "onCancel:");
                    result.success(emptyList<Map<String, Any>>())
                }

                override fun onResult(localMedias: ArrayList<LocalMedia?>?) {
                    Log.i("pickerImage", "onResult:");
                    val map = localMedias?.filterNotNull()?.map { media ->
                        Log.i("pickerImage", "是否压缩:" + media.isCompressed);
                        Log.i("pickerImage", "压缩:" + media.compressPath);
                        Log.i("pickerImage", "原图:" + media.path);
                        Log.i("pickerImage", "绝对路径:" + media.realPath);
                        Log.i("pickerImage", "是否裁剪:" + media.isCut);
                        Log.i("pickerImage", "裁剪:" + media.cutPath);
                        Log.i("pickerImage", "是否开启原图:" + media.isOriginal);
                        Log.i("pickerImage", "原图路径:" + media.originalPath);
                        Log.i("pickerImage", "宽高: " + media.width + "x" + media.height);
                        Log.i("pickerImage", "Size: " + media.size)
                        Log.i("pickerImage", "mimeType: " + media.mimeType)
                        val hashMap = HashMap<String, Any>()
                        if (media.isCut && !media.isCompressed) {
                            // 裁剪过
                            hashMap["path"] = media.cutPath;
                        } else if (media.isCompressed || (media.isCut && media.isCompressed)) {
                            // 压缩过,或者裁剪同时压缩过,以最终压缩过图片为准
                            hashMap["path"] = media.compressPath;
                        } else {
                            // 原图
                            hashMap["path"] = media.realPath;
                        }
                        if (isEnableCrop && (media.mimeType == "image/gif" || media.mimeType == "image/webp")) {
                            hashMap["path"] = media.realPath
                        }
                        hashMap["size"] = media.size
                        hashMap["height"] = media.height
                        hashMap["width"] = media.width
                        hashMap
                    }?.toList()
                    result.success(map)
                }
            })
    }

    private fun pickerVideo(argument: Any?, result: Result) {
        if (argument == null || argument !is Map<*, *>) return;
        val maxNum = argument["maxNum"]?.let { it as Int } ?: 1
        PictureSelector.create(activity)
            .openGallery(SelectMimeType.ofVideo())
            .setImageEngine(GlideEngine.createGlideEngine())
            .setMaxSelectNum(maxNum)
            .isAutoVideoPlay(true)
            .isPreviewVideo(true)
            .isVideoPauseResumePlay(true)
//            .setSandboxFileEngine { context, srcPath, mineType, call ->
//                if (call != null) {
////                    val sandboxPath =
////                        SandboxTransformUtils.copyPathToSandbox(context, srcPath, mineType)
//                    call.onCallback(srcPath, srcPath);
//                }
//            }
            .forResult(object : OnResultCallbackListener<LocalMedia?> {
                override fun onCancel() {
                    Log.i("pickerImage", "onCancel:");
                    result.success(emptyList<Map<String, Any>>())
                }

                override fun onResult(localMedias: kotlin.collections.ArrayList<LocalMedia?>?) {
                    Log.i("pickerImage", "onResult:");
                    val map = localMedias?.filterNotNull()?.map { media ->
                        Log.i("pickerImage", "是否压缩:" + media.isCompressed);
                        Log.i("pickerImage", "压缩:" + media.compressPath);
                        Log.i("pickerImage", "原图:" + media.path);
                        Log.i("pickerImage", "绝对路径:" + media.realPath);
                        Log.i("pickerImage", "是否裁剪:" + media.isCut);
                        Log.i("pickerImage", "裁剪:" + media.cutPath);
                        Log.i("pickerImage", "是否开启原图:" + media.isOriginal);
                        Log.i("pickerImage", "原图路径:" + media.originalPath);
                        Log.i("pickerImage", "宽高: " + media.width + "x" + media.height);
                        Log.i("pickerImage", "Size: " + media.size)
                        Log.i("pickerImage", "mimeType: " + media.mimeType)
                        val hashMap = HashMap<String, Any>()
                        hashMap["size"] = media.size
                        hashMap["height"] = media.height
                        hashMap["width"] = media.width
                        hashMap["path"] = media.realPath
                        hashMap
                    }?.toList()
                    result.success(map)
                }
            })
    }



    private fun pickerAudio(argument: Any?, result: Result) {
        PictureSelector.create(activity)
            .openGallery(SelectMimeType.ofAudio())
            .setImageEngine(GlideEngine.createGlideEngine())
            .setMaxSelectNum(1)
            .isPreviewAudio(true)
            .setRecordAudioInterceptListener(object : OnRecordAudioInterceptListener {
                override fun onRecordAudio(fragment: Fragment?, requestCode: Int) {

                }

            })
            .isVideoPauseResumePlay(true)
            .setSandboxFileEngine { context, srcPath, mineType, call ->
                if (call != null) {
                    val sandboxPath =
                        SandboxTransformUtils.copyPathToSandbox(context, srcPath, mineType)
                    call.onCallback(srcPath, sandboxPath);
                }
            }
            .forResult(object : OnResultCallbackListener<LocalMedia?> {
                override fun onCancel() {
                    Log.i("pickerAudio", "onCancel:");
                    result.success(emptyList<Map<String, Any>>())
                }

                override fun onResult(localMedias: kotlin.collections.ArrayList<LocalMedia?>?) {
                    Log.i("pickerAudio", "onResult:");
                    val map = localMedias?.filterNotNull()?.map { media ->
                        Log.i("pickerImage", "是否压缩:" + media.isCompressed);
                        Log.i("pickerImage", "压缩:" + media.compressPath);
                        Log.i("pickerImage", "原图:" + media.path);
                        Log.i("pickerImage", "绝对路径:" + media.realPath);
                        Log.i("pickerImage", "是否裁剪:" + media.isCut);
                        Log.i("pickerImage", "裁剪:" + media.cutPath);
                        Log.i("pickerImage", "是否开启原图:" + media.isOriginal);
                        Log.i("pickerImage", "原图路径:" + media.originalPath);
                        Log.i("pickerImage", "宽高: " + media.width + "x" + media.height);
                        Log.i("pickerImage", "Size: " + media.size)
                        Log.i("pickerImage", "mimeType: " + media.mimeType)
                        val hashMap = HashMap<String, Any>()
                        hashMap["size"] = media.size
                        hashMap["height"] = media.height
                        hashMap["width"] = media.width
                        hashMap["path"] = media.realPath
                        hashMap
                    }?.toList()
                    result.success(map)
                }
            })
    }


    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
    }

    override fun onDetachedFromActivityForConfigChanges() {}

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {}

    override fun onDetachedFromActivity() {}

}
